package hello.reddwarf.server;

import java.io.Serializable;

import com.sun.sgs.app.*;
import com.sun.sgs.app.util.ScalableHashMap;

import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Сервер игры. Этот класс автоматически загружается платформой,
 * инициализируется и его платформа уведомляет о новых подключениях.
 */
public class Server implements AppListener, Serializable, ManagedObject {

    /**
     * Поскольку объект Serializable, то неплохо бы добавить это поле
     */
    private static final long serialVersionUID = 1L;

    private static final Logger logger = Logger.getLogger(Server.class.getName());

    public ManagedReference<ScalableHashMap<String, Player>> onlinePlayersRef;

    @Override
    public void initialize(Properties props) {

        logger.info("Starting new Rock-Paper-Scissors Server. Initialized database.");

        ScalableHashMap<String, Player> onlinePlayers = new ScalableHashMap<String, Player>();
        onlinePlayersRef = AppContext.getDataManager().createReference(onlinePlayers);

        AppContext.getTaskManager().schedulePeriodicTask(new OnlineLoggerTask(onlinePlayersRef), 0, 5000);
    }

    @Override
    public ClientSessionListener loggedIn(ClientSession session) {
        String name = session.getName();
        logger.log(Level.INFO, "Client login: {0}", name);

        // Подключился пользователь. Необходимо загрузить его из базы данных, либо зарегистрировать нового
        Player player = loadOrRegister(name);

        // Установим игроку сессию. Сессия - это объект, через который осуществляется
        // сетевое взаимодействие - отсылка сообщений на клиент
        player.setSession(session);
        // Уведомляем игрока о том, что он подключился
        player.connected();
        // Добавим его в список онлайн-игроков
        onlinePlayersRef.get().put(player.name, player);

        return player;
    }

    private Player loadOrRegister(String name) {
        try {
            return (Player) AppContext.getDataManager().getBindingForUpdate("player." + name);
        } catch (NameNotBoundException e) {
            // Попытка загрузить объект и перехват исключения -
            // единственный способ узнать, есть ли такой объект в базе
            logger.log(Level.INFO, "Registering new player {0}", name);
            Player player = new Player(name, this);
            AppContext.getDataManager().setBinding("player." + name, player);
            return player;
        }

    }

    public void disconnect(Player player) {
        // Игрок отключился. Удалим его из списка онлайн
        onlinePlayersRef.get().remove(player.name);
    }
}
